#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <aio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#define BUF_SIZE 1024

int main(int argc, const char *argv[]){
    if(argc < 2) return -1;
    int fd = open(argv[1], O_RDONLY);
    if(fd < 2) {
       printf("open %s error: %s\n", argv[1], strerror(errno));
       return -1;
    }
   
    off_t f_pos = 0; // 已读数据的偏移  fseek(FILE *, off_t offset, int whence)
    char fulldata[8192] = ""; // 全数据暂存区
    char databuf[BUF_SIZE] = "";
    while(1){
        // 异步读的过程：
        // 1) 创建aiocb结构体类型变量 2）设置相关属性 3）开始异步读
        // 4) 等待读取完成   5）获取读取的实际数据大小 6）打印读取数据内容
        struct aiocb cb1; // 异步操作控制块
        cb1.aio_fildes = fd; // 异步操作的文件FD
        cb1.aio_buf = databuf; // 读取数据存储的空间位置,   缓冲区
        cb1.aio_nbytes = BUF_SIZE; // 期待读取的字节数
        cb1.aio_offset = f_pos; // 读取文件数据的位置（偏移量）
        cb1.aio_reqprio = 1; // 请求优先级

        int ret = aio_read(&cb1); // 开始异步读取数据
        if(ret != 0){
            perror("aio_read");
            break;
        }else{
           // 提交任务成功, 等待任务完成
           while(aio_error(&cb1) == EINPROGRESS);

           // 异步读完成，打印异步操作状态
           // printf("aiocb status is %d\n", aio_error(&cb1));
           ssize_t len = aio_return(&cb1); // 获取实际数据的长度
            
           strncpy(fulldata+f_pos, databuf, len);
           f_pos += len; // 记录上一次读取数据的文件光标位置
           bzero(databuf, BUF_SIZE); // 清空缓冲区数据
           if(len < BUF_SIZE) break;
        }
    }
	printf("aio read data:\n %s\n",fulldata);
    close(fd);
    return 0;
}
